using System.Collections.Generic;
using System.Linq;
using StackCalc.Instructions;
using StackCalc.Parsing.ParsingUnits;

namespace StackCalc.Parsing
{
	/// <summary>
	/// Parses input strings.
	/// </summary>
	public class InputParser
	{
		/// <summary>
		/// Stores all parsing units.
		/// </summary>
		private readonly IList<IParsingUnit<IInstruction>> _registeredParsingUnits = new List<IParsingUnit<IInstruction>>
		                                                                                         	{
																										new IntegerParser(),
																										new OperatorParser(),
																										new SpecialCharacterParser(),
																										new BracedExpressionParser(),
																										new NegationParser(),
																										new CopyParser(),
																										new DeleteParser(),
																										new ApplyParser(),
																										new PrintNumberParser(),
																										new PrintTextParser(),
																										new ReadInstructionParser(),

																										// its important that this is the last entry!
																										new CharacterParser()
		                                                                                         	};

		public bool HasSyntaxError(string input)
		{
			// if any parser reports incorrect syntax return true
			return _registeredParsingUnits.Any(x => x.HasSyntaxError(input));
		}

		public string GetErrorDescription(string input)
		{
			// get error description from the first parser with syntax error
			return _registeredParsingUnits.First(x => x.HasSyntaxError(input)).GetErrorDescription();
		}

		public string Trunkate(string input)
		{
			// the first parser that can parse shall truncate the input
			return _registeredParsingUnits.First(x => x.CanParse(input)).Trunkate(input);
		}

		public IInstruction Parse(string input)
		{
			// use the first parser that can parse to get the instruction
			return _registeredParsingUnits.First(x => x.CanParse(input)).Parse(input);
		}
	}
}
